﻿using UnityEngine;
using System.Collections.Generic;

namespace GameDesigner
{
    public enum StateMachineUpdateMode
    {
        Update = 1,
        LateUpdate = 2,
        FixedUpdate = 4,
    }

    /// <summary>
    /// 状态基类
    /// </summary>
    [System.Serializable]
    public class StateBase
    {
        public string name;
        [SerializeField] private RefIdentity _id;
        /// <summary>
        /// 状态id, 只能是状态id, 不能是其他, 如果需要获取Action的Id, 需要使用Action.GetActionIndex方法
        /// </summary>
        public RefIdentity Id { get => _id ??= new(); set => _id = value; }
#if UNITY_EDITOR
        [System.NonSerialized] public int preId;
#endif
#if UNITY_2020_1_OR_NEWER
        [NonReorderable]
#endif
        public BehaviourBase[] behaviours;
        public IStateMachine stateMachine;
#if UNITY_EDITOR
        [HideInInspector]
        public bool foldout = true;
        public Rect rect;
#endif

        /// <summary>
        /// 添加状态行为组件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T AddComponent<T>() where T : BehaviourBase, new()
        {
            return AddComponent(new T());
        }

        /// <summary>
        /// 添加状态行为组件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="component"></param>
        /// <returns></returns>
        public T AddComponent<T>(T component) where T : BehaviourBase
        {
            return (T)AddComponentInternal(component);
        }

        public void AddComponent(params BehaviourBase[] behaviours)
        {
            if (behaviours == null)
                return;
            foreach (var component in behaviours)
                AddComponentInternal(component);
        }

        private BehaviourBase AddComponentInternal(BehaviourBase component)
        {
            var type = component.GetType();
            component.name = type.ToString();
            component.Id = Id;
            component.stateMachine = stateMachine;
            if (component is ActionBehaviour actionBehaviour)
                actionBehaviour.Action = (StateAction)this;
            else if (component is TransitionBehaviour transitionBehaviour)
                transitionBehaviour.Transition = (Transition)this;
#if UNITY_EDITOR
            component.InitMetadatas();
#endif
            component.InitUpdateMode(type);
            component.OnInit();
            ArrayHelper.Add(ref behaviours, component);
            return component;
        }

        /// <summary>
        /// 获取状态组件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T GetComponent<T>() where T : BehaviourBase
        {
            for (int i = 0; i < behaviours.Length; i++)
                if (behaviours[i] is T component)
                    return component;
            return null;
        }

        /// <summary>
        /// 获取多个状态组件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T[] GetComponents<T>() where T : BehaviourBase
        {
            var components = new List<T>();
            for (int i = 0; i < behaviours.Length; i++)
                if (behaviours[i] is T component)
                    components.Add(component);
            return components.ToArray();
        }
    }
}